// STL
#include <functional>                             // std::function<>
#include <vector>                                 // std::vector<>

// jScience
#include "jrandnum.hpp"                           // rand_num_uniform_Mersenne_twister()

// this
#include "statsxx/optimization/EA/EAParam.hpp"    // EAParam
#include "statsxx/optimization/EA/Individual.hpp" // Individual


//
// DESC: Mutates an individual.
//
inline void mutate(
                   Individual                                                    &child,
                   // -----
                   std::function<double(const int, const std::vector<double> &)>  new_gene,
                   std::function<double(const int, const std::vector<double> &)>  mutate_gene,
                   // -----
                   const EAParam                                                 &param
                   )
{
    for( auto i = 0; i < child.genome.size(); ++i )
    {
        double pm = rand_num_uniform_Mersenne_twister(0., 1.);

        if( pm < param.prob_mutate )
        {
            double pnew = rand_num_uniform_Mersenne_twister(0., 1.);

            if( pnew < param.prob_new_gene )
            {
                child.genome[i] = new_gene(
                                           i,
                                           child.genome
                                           );
            }
            else
            {
                child.genome[i] = mutate_gene(
                                              i,
                                              child.genome
                                              );
            }
        }
    }
}


